package com.stake.security.filter;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.jdo.PersistenceManagerFactory;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

import com.google.api.client.auth.oauth2.draft10.AccessTokenResponse;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAccessTokenRequest.GoogleAuthorizationCodeGrant;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.code.linkedinapi.client.oauth.LinkedInAccessToken;
import com.google.code.linkedinapi.client.oauth.LinkedInApiConsumer;
import com.google.code.linkedinapi.client.oauth.LinkedInOAuthService;
import com.google.code.linkedinapi.client.oauth.LinkedInRequestToken;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

@Component("preAuthGaeFilter") 
public class GaePreAuthFilter extends GenericFilterBean{
	
	public static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(GaePreAuthFilter.class);
	
	private static final String CALLBACK_URL = "http://www.galaxy-space.com/public/googleRedirect.htm";
	private static final HttpTransport TRANSPORT = new NetHttpTransport();
	private static final JsonFactory JSON_FACTORY = new JacksonFactory();

	// FILL THESE IN WITH YOUR VALUES FROM THE API CONSOLE
	private static final String CLIENT_ID = "916376634676.apps.googleusercontent.com";
	private static final String CLIENT_SECRET = "BK3YU3NWk7YKRlx3L9p7UcHf";
	
	@Autowired
	@Qualifier("persistenceManagerFactory") 
	PersistenceManagerFactory persistenceManagerFactory;

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if(authentication == null){
			// User isn't authenticated. Check if there is a Google Accounts user
			if(((HttpServletRequest)request).getServletPath().contains("googleRedirect.htm")){
				// User has returned after authenticating through GAE. Need to authenticate to Spring Security.
				GoogleAuthorizationCodeGrant authRequest = new GoogleAuthorizationCodeGrant(TRANSPORT,
						JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, request.getParameter("code"), CALLBACK_URL);
				authRequest.useBasicAuthorization = false;
				AccessTokenResponse authResponse = authRequest.execute();
				Map<String, String> userInfoMap = new HashMap<String, String>();
				try {
					userInfoMap = getUserInfoMap(authResponse.accessToken);
				} catch (Exception e) { 
					e.printStackTrace();
				}
				request.setAttribute("newGoogleUser", userInfoMap);
			} else if(((HttpServletRequest)request).getServletPath().contains("linkedin/authRedirect.htm")){
				// User has returned after authenticating through linkedin. Need to authenticate to Spring Security.
				final String consumerKeyValue = "57vupwf7qm04";
				final String consumerSecretValue = "aHh3om7Zf9q5esFS";
				LinkedInApiConsumer apiConsumer = new LinkedInApiConsumer(consumerKeyValue, consumerSecretValue);
				final LinkedInOAuthService oauthService = new com.stake.web.controller.LinkedInOAuthServiceImpl(apiConsumer);
				
				LinkedInRequestToken requestToken = (LinkedInRequestToken) ((HttpServletRequest)request).getSession().getAttribute("requestToken");
				LinkedInAccessToken accessToken = oauthService.getOAuthAccessToken(requestToken, request.getParameter("oauth_verifier"));
				
				
				 ((HttpServletRequest)request).getSession().setAttribute("linkedInaccessToken", accessToken);
			}
			
		}
		chain.doFilter(request, response);
	}
	
	

	
	private Map<String, String> getUserInfoMap(String accessToken) throws Exception {
		InputStream input2 = new URL("https://www.googleapis.com/oauth2/v1/userinfo?access_token="
				+ accessToken).openStream();
		StringBuilder data2 = new StringBuilder();
		int c2;
		while ((c2 = input2.read()) != -1) {
			data2.append((char) c2);
		}
		Type resultMapType = new TypeToken<HashMap<String, String>>(){}.getType();
		Map<String, String> infoMap = new Gson().fromJson(data2.toString(), resultMapType);
		return infoMap;
	}

}
